package com.google.code.server4j.parser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.dom4j.util.XMLErrorHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class XMLValidation {
    public static final int Monde_DTD = 0; // DTD形式验证

    public static final int Monde_Schema = 1; // Schema验证

    /**
     * 
     * @param xmlFile
     *            xml文件路径
     * @param validationFile
     *            校验文件路径
     * @param monde
     *            校验类型
     * @return 校验是否成功
     */
    public static boolean testXMLFile(String xmlFile, String validationFile,
            int monde) {
        boolean flag = true;
        if (monde == Monde_DTD) {// 如果是dtd校验调用校验dtd的（9php.com）方法
            flag = testXMLByDTD(xmlFile, validationFile);
        } else if (monde == Monde_Schema) {// 如果是xsd校验调用校验xsd的（9php.com）方法
            flag = testXMLByXsd(xmlFile, validationFile);
        } else {
            flag = false;
        }
        return flag;
    }

    /**
     * 校验 dtd 的（9php.com）方法
     * 
     * @param xmlFile
     *            xml文件路径
     * @param validationFile
     *            校验文件路径
     * @return 校验是否成功 
     */
    public static boolean testXMLByDTD(final String xmlFile,
            final String validationFile) {
        /*
         * 此类实体包括在 DTD 内引用的（9php.com）外部 DTD
         * 子集和外部参数实体（无论哪种情形,仅在在解析器都读取外部参数实体时）
         * 和在文档元素内引用的（9php.com）外部通用实体（如果解析器读取外部通用实体）
         */
        EntityResolver resolver = new EntityResolver() {// 应用程序解析外部实体
            public InputSource resolveEntity(String publicId, String systemId) {
                InputStream is = null;
                try {
                    is = new FileInputStream(validationFile);// 读取dtd文档
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    return null;
                }
                InputSource ins = new InputSource(is);
                ins.setPublicId(publicId);
                ins.setSystemId(systemId);
                return ins;// 返回 InputSource实例
            }
        };
        SAXReader reader = new SAXReader(true);
        reader.setEntityResolver(resolver); // 向SAX 驱动器注册一EntityResolver个实例。
        boolean flag = validate(xmlFile, reader);// 调用验证方法
        return flag;
    }

    /**
     * 验证 xsd 方法
     * 
     * @param xmlFile
     *            xml文件路径
     * @param validationFile
     *            校验文件路径
     * @return 校验是否成功
     */
    public static boolean testXMLByXsd(final String xmlFile,final String validationFile) {
        SAXReader reader = new SAXReader(true);// 创建SAXReader对象并制定需要验证
                                               // 也可通过reader.setValidation(true)来指定
        try {
        	// 设置功能标志的 值name -功能名称,它是一个完全限定 URI。value - 请求的 功能值（true 或false）。
            reader.setFeature("http://xml.org/sax/features/validation", true);
            reader.setFeature("http://apache.org/xml/features/validation/schema", true);
            reader.setFeature("http://apache.org/xml/features/validation/schema-full-checking",true);
            // 设置属性的 值 name - 属性名称,它是一个完全限定 URI。value - 请求的 属性值
            reader.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation",validationFile);
        } catch (SAXException e) {
            e.printStackTrace();
            return false;// 如果捕获异常 则返回false
        }
        boolean flag = validate(xmlFile, reader);// 调用验证方法
        return flag;
    }

    /**
     * 
     * @param xmlFile xml文件路径
     * @param validationFile 校验文件路径 
     * @param reader  SAXReader 对象
     * @return 校验是否成功
     */
    private static boolean validate(final String xmlFile, final SAXReader reader) {
        XMLErrorHandler errorHandle = new XMLErrorHandler();// 错误处理类实例
        reader.setErrorHandler(errorHandle);// 向 XML 阅读器注册一个实例
        File file = new File(xmlFile);
        InputStream is = null;
        if (file.exists() && file.isFile()) {
            try {
                is = new FileInputStream(file);// 读取xml
                InputStreamReader in = new InputStreamReader(is, "utf-8");
                Document doc = reader.read(in);
                System.out.println(doc.asXML());
            } catch (FileNotFoundException e) {// 如果出现异常返回false
                e.printStackTrace();
                return false;
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return false;
            } catch (DocumentException e) {
                e.printStackTrace();
                return false;
            }
        } else
            return false;
        if (errorHandle.getErrors().hasContent()) {// 如果错误处理类实例中包含错误信息返回false;
        	System.out.println("error : "+errorHandle.getErrorQName().toString());
        	System.out.println("warning : "+errorHandle.getWarningQName().toString());
            return false;
        }
        return true;
    }
    
    
    public static void main(String[] args) {
//		String xsdFilePath = "C:\\web-app_2_5.xsd";
//		String xmlFileName = "C:\\web.xml";
		
		String xsdFilePath = "E:\\IDE\\eclipse-jee-indigo-win32\\workspace\\zmina\\src\\com\\dom4j\\rule.dtd";
		String xmlFileName = "E:\\IDE\\eclipse-jee-indigo-win32\\workspace\\zmina\\src\\com\\dom4j\\stu1.xml";
		
//    	boolean isOk = testXMLByXsd(xmlFileName,xsdFilePath);
    	boolean isOk = testXMLByDTD(xmlFileName,xsdFilePath);
    	System.out.println(isOk);
    	
    }
    
    
}